package com.write.ibatis.executor;

import com.write.ibatis.config.Configuration;
import com.write.ibatis.config.JdbcProperties;
import com.write.ibatis.config.MapperStatement;

import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class SimpleExecutor implements Executor {
    private JdbcProperties jdbcProperties;

    public SimpleExecutor(JdbcProperties jdbcProperties) {
        this.jdbcProperties = jdbcProperties;
    }

    @Override
    public <E> List<E> query(MapperStatement mapperStatement, Object paramter) {
        ArrayList<E> ret = new ArrayList<>();
        ResultSet resultSet = null;
        try {
            Class.forName(jdbcProperties.getDriver());
            Connection connection = DriverManager.getConnection(jdbcProperties.getUrl(), jdbcProperties.getUsername(), jdbcProperties.getPassword());
            PreparedStatement preparedStatement = connection.prepareStatement(mapperStatement.getSql());
            paramterize(preparedStatement,paramter);
            resultSet = preparedStatement.executeQuery();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        handlerResultSet(resultSet,ret, mapperStatement.getResultType());
        return ret;
    }

    private <E> void handlerResultSet(ResultSet resultSet, ArrayList<E> ret, String resultType) {
        try {
            Class<E> clazz = (Class<E>) Class.forName(resultType);
            while (resultSet.next()){
                E e = clazz.newInstance();
                Field[] fields = clazz.getDeclaredFields();
                for (Field field : fields) {
                    field.setAccessible(true);
                    String fieldName = field.getName();
                    Type genericType = field.getGenericType();
                    if(genericType.toString().equals("class java.lang.String")){
                        String value1 = resultSet.getString(fieldName);
                        field.set(e,value1);
                    }else if (genericType.toString().equals("long")){
                        long value1 = resultSet.getLong(fieldName);
                        field.set(e,value1);
                    }else if(genericType.toString().equals("class java.lang.Integer")){
                        int value1 = resultSet.getInt(fieldName);
                        field.set(e,value1);
                    }
                }
                ret.add(e);
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

    }


    private void paramterize(PreparedStatement preparedStatement, Object paramter) throws SQLException {
        if(paramter instanceof String){
            preparedStatement.setString(1,(String) paramter);
        }else if (paramter instanceof Long){
            preparedStatement.setLong(1,(Long) paramter);
        }else if (paramter instanceof Integer){
            preparedStatement.setInt(1,(Integer)paramter);
        }
    }


}
